import Input from '@/components/Input'
import NavBar from '@/components/NavBar'
import { useFormik } from 'formik'
import styles from './index.module.scss'
import * as Yup from 'yup'
import { useDispatch } from 'react-redux'
import { Authorizations, sendCodes } from '@/store/action/user'
import { Toast } from 'antd-mobile'
import { useEffect, useRef, useState } from 'react'
import { useHistory, useLocation } from 'react-router-dom'

type FormValues = {
  mobile: string
  code: string
}

export default function Login() {
  const history = useHistory()
  // 🔔注意：useLocation 传入的泛型用于指定 state 对象格式
  const location = useLocation<{ from: string }>()
  // 官方文档：https://formik.org/docs/api/useFormik
  // 创建 formik，需要传入初始化数据和表单提交事件
  const formik = useFormik({
    // 表单初始值
    initialValues: {
      mobile: '13535337057',
      code: '123456',
    } as FormValues,
    // 提交表单
    onSubmit: async (values) => {
      console.log('当前表单的数据为', values)
      // 发送请求获取用户认证 token
      await dispatch(Authorizations(values))
      // 成功提示
      Toast.show({ content: '登录成功' })
      // 获取回跳页面，若没有则跳转首页
      if (location.state) {
        // 替换成回跳的页面
        history.replace(location.state.from)
      } else {
        // 跳转到首页
        history.push('/home')
      }
    },
    // // 校验表单数据 - 普通写法
    // validate: (values) => {
    //   // 通过 TS 的断言指定格式
    //   const error = {} as FormValues
    //   if (!/^1[3-9]\d{9}$/.test(values.mobile)) error.mobile = '手机号格式错误'
    //   if (!/^\d{6}$/.test(values.code)) error.code = '验证码格式错误'
    //   // 返回错误对象
    //   return error
    // },
    // Yup 表单校验 - 更专业写法
    validationSchema: Yup.object().shape({
      // 手机号
      mobile: Yup.string()
        .required('请输入手机号码')
        .matches(/^1[3-9]\d{9}$/, '手机号格式错误'),
      // 验证码
      code: Yup.string()
        .required('请输入验证码')
        .matches(/^\d{6}$/, '验证码格式错误'),
    }),
  })

  const dispatch = useDispatch()
  const [time, setTime] = useState(0)
  const timerId = useRef(-1)
  const handleSendCodes = async () => {
    // 倒计时没结束，直接退出
    if (time > 0) return
    // 检查手机号格式
    if (formik.errors.mobile) return Toast.show({ content: formik.errors.mobile })
    // 🔔调用异步 action ，内部发送请求获取验证码
    await dispatch(sendCodes(formik.values.mobile))
    // 成功提示
    Toast.show({ content: '验证码发送成功' })
    // 开启倒计时
    setTime(60)
    timerId.current = window.setInterval(() => {
      // 💥当我们每次都想要获取到最新的状态，需要写成 箭头函数 的形式
      setTime((time) => {
        // console.log('定时器内部的time值', time)
        if (time === 1) clearInterval(timerId.current)
        return time - 1
      })
    }, 1000)
  }

  useEffect(() => {
    // 清理函数
    return () => {
      // 组件卸载清理定时器，避免内存泄漏
      clearInterval(timerId.current)
    }
  }, [])

  return (
    <div className={styles.root}>
      <NavBar>登录</NavBar>
      <div className='content'>
        {/* 标题 */}
        <h3>短信登录</h3>
        <form onSubmit={formik.handleSubmit}>
          {/* 手机号输入框 */}
          <div className='input-item'>
            <Input
              autoFocus
              className='input'
              placeholder='请输入手机号'
              autoComplete='off'
              type='text'
              name='mobile'
              maxLength={11}
              // 🔔优化：碰过表单并失去焦点，才展示错误信息
              errMsg={formik.touched.mobile ? formik.errors.mobile : ''}
              // formik.touched 需配合 handleBlur 使用
              onBlur={formik.handleBlur}
              value={formik.values.mobile}
              onChange={formik.handleChange}
            />
          </div>

          {/* 短信验证码输入框 */}
          <div className='input-item'>
            <Input
              className='input'
              placeholder='请输入验证码'
              autoComplete='off'
              type='text'
              name='code'
              maxLength={6}
              errMsg={formik.touched.code ? formik.errors.code : ''}
              onBlur={formik.handleBlur}
              extra={
                <span onClick={handleSendCodes}>
                  {time === 0 ? '获取验证码' : `${time}秒后重试`}
                </span>
              }
              value={formik.values.code}
              onChange={formik.handleChange}
            />
          </div>

          {/* 登录按钮 */}
          <button type='submit' className='login-btn' disabled={!formik.isValid}>
            登录
          </button>
        </form>
      </div>
    </div>
  )
}
